package com.mandao.oneplat.boot.dao;

import com.mandao.oneplat.boot.OnePlatConfig;
import com.mandao.oneplat.boot.util.PackageUtil;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.bson.Document;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by sunson on 2017/3/29.
 */
public class OneMongoDaoProxy {

    private OnePlatConfig oneOption;
    private MongoDatabase database;
    private Map<String, OneMongoCollection> collectionMap;

    public OneMongoDaoProxy(OnePlatConfig oneOption) throws IOException {
        this.oneOption = oneOption;
        collectionMap = new HashMap<>();
        // 初始化连接
        MongoClient mongoClient = new MongoClient(oneOption.getMongoHost(), oneOption.getMongoPort());
        database = mongoClient.getDatabase(oneOption.getMongoDb());
        //
        initDB();
    }

    void initDB() throws IOException {
        // 初始化Table
        List<Class> classList = PackageUtil.scanPackages(oneOption.getBasePackages());

        for (Class clazz : classList) {
            String cname;
            if (!clazz.isAnnotationPresent(AOneMongoTable.class)) {
                continue;
            }
            AOneMongoTable aOneMongoTable = (AOneMongoTable) clazz.getAnnotation(AOneMongoTable.class);
            cname = aOneMongoTable.value();
            if (StringUtils.isEmpty(cname)) {
                cname = clazz.getSimpleName();
            }
            OneMongoCollection oneMongoCollection = new OneMongoCollection();
            oneMongoCollection.setName(cname);
            Map<String, Field> propMap = new HashMap<>();
            FieldUtils.getFieldsListWithAnnotation(clazz, AOneMongoField.class).forEach(field -> {
                AOneMongoField aOneMongoField = field.getAnnotation(AOneMongoField.class);
                String name = aOneMongoField.value();
                if (StringUtils.isEmpty(name)) {
                    name = field.getName();
                }
                propMap.put(name, field);
                if (field.getAnnotation(AOneMongoId.class) != null) {
                    oneMongoCollection.setIdField(field);
                }
            });
            oneMongoCollection.setPropMap(propMap);
            // 检测是否创建了集合
            MongoCollection<Document> document = database.getCollection(cname);
            if (document == null) {
                database.createCollection(cname);
            }
            oneMongoCollection.setDocument(database.getCollection(cname));
            collectionMap.put(cname, oneMongoCollection);
        }
    }

    public OneMongoCollection findCollection(Class clazz) {
        if (!clazz.isAnnotationPresent(AOneMongoTable.class)) {
            throw new RuntimeException("实体类必须注解为AOneMongoTable");
        }
        AOneMongoTable aOneMongoTable = (AOneMongoTable) clazz.getAnnotation(AOneMongoTable.class);
        String cname = aOneMongoTable.value();
        if (StringUtils.isEmpty(cname)) {
            cname = clazz.getSimpleName();
        }
        if (!collectionMap.containsKey(cname)) {
            throw new RuntimeException("未知的实体类");
        }
        return collectionMap.get(cname);
    }
}
